/***************************************************************************
 *   Copyright (C) 2008, 2009, 2010 by Lasse Liehu                         *
 *   lliehu@kolumbus.fi                                                    *
 *                                                                         *
 *   This program is free software you can redistribute it and/or modify   *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation either version 2 of the License, or      *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY without even the implied warranty of         *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program if not, write to the                          *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "googlelogindata.h"

#include <QString>

#include <QInputDialog>
#include <QLineEdit>
#include <QCoreApplication>

// Threading stuff
#include <QThread>
#include <QMutex>
#include <QMutexLocker>

//BEGIN GoogleLoginDataPrivate
class GoogleLoginDataPrivate
{
    public:
        QString email;
        QString password;
        bool passwordGiven;
        bool isPasswordSaved;
        bool alwaysAskPassword;
        QString sid;

        // Mutexes
        mutable QMutex emailMutex;
        mutable QMutex passwordMutex;
        mutable QMutex passwordGivenMutex;
        mutable QMutex isPasswordSavedMutex;
        mutable QMutex alwaysAskPasswordMutex;
        mutable QMutex sidMutex;
};
//END GoogleLoginDataPrivate

class GoogleLoginData::SleeperThread : public QThread
{
    public:
        void run() {}
        static void msleep(unsigned long msecs)
        {
            QThread::msleep(msecs);
        }
};

GoogleLoginData::GoogleLoginData() : d(new GoogleLoginDataPrivate)
{
    d->passwordGiven = false;
    d->isPasswordSaved = false;
    d->alwaysAskPassword = false;
}

GoogleLoginData::~GoogleLoginData()
{
    delete d;
}

/**
 * @param type When this is set to GoogleLoginData::Saved, the returned
 *             password will be the one that should be saved in the settings
 *             or displayed in the settings dialog.
 */
QString GoogleLoginData::password(PasswordType type)
{
    bool ask = false;

    d->passwordMutex.lock();
    if (isAlwaysAskPasswordOn() ) ask = true;
    else if ( d->password.isEmpty() && type == Normal && (!email().isEmpty()) )
    {
        ask = true;
    }
    d->passwordMutex.unlock();

    // asking for the password
    if (ask)
    {
        // WANTED: password
        d->passwordGivenMutex.lock();
        d->passwordGiven = false;
        d->passwordGivenMutex.unlock();
        emit passwordWanted();

        // waiting for someone to give us a password
        d->passwordGivenMutex.lock();
        while (!d->passwordGiven)
        {
            d->passwordGivenMutex.unlock();
            SleeperThread::msleep(500); // TODO do this in the right way!
            d->passwordGivenMutex.lock();
        }
        d->passwordGivenMutex.unlock();
    }

    QMutexLocker locker(&d->passwordMutex);
    if (type == Saved && !isPasswordSaved() ) return "";
    else return d->password;
}

QString GoogleLoginData::email() const
{
    QMutexLocker locker(&d->emailMutex);
    return d->email;
}

QString GoogleLoginData::sid() const
{
    QMutexLocker locker(&d->sidMutex);
    return d->sid;
}

bool GoogleLoginData::isPasswordSaved() const
{
    QMutexLocker locker(&d->isPasswordSavedMutex);
    return d->isPasswordSaved;
}

bool GoogleLoginData::isAlwaysAskPasswordOn() const
{
    QMutexLocker locker(&d->alwaysAskPasswordMutex);
    return d->alwaysAskPassword;
}

void GoogleLoginData::connectDefaultPasswordAsker()
{
    connect(this, SIGNAL(passwordWanted() ), this, SLOT(askPasswordFromUser() ));
}

void GoogleLoginData::disconnectCurrentPasswordAsker()
{
    disconnect(this, SIGNAL(passwordWanted() ), 0, 0);
}

void GoogleLoginData::setPassword(const QString& passwd)
{
    QMutexLocker locker(&d->passwordMutex);
    bool passwordChangedL = passwd != d->password;
    d->password = passwd;
    if (passwordChangedL)
    {
        emit passwordChanged(d->password);
        d->sidMutex.lock();
        if ( ! d->sid.isEmpty() )
        {
            d->sid.clear();
            emit sidChanged(d->sid);
        }
        d->sidMutex.unlock();
    }
    d->passwordGivenMutex.lock();
    d->passwordGiven = true;
    d->passwordGivenMutex.unlock();
}

void GoogleLoginData::setEmail(const QString& email)
{
    QMutexLocker locker(&d->emailMutex);
    bool emailChangedL = email != d->email;
    d->email = email;
    if (emailChangedL)
    {
        emit emailChanged(d->email);
        d->sidMutex.lock();
        if ( ! d->sid.isEmpty() )
        {
            d->sid.clear();
            emit sidChanged(d->sid);
        }
        d->sidMutex.unlock();
    }
}

void GoogleLoginData::setSid(const QString& sid)
{
    QMutexLocker locker(&d->sidMutex);
    bool sidChangedL = sid != d->sid;
    d->sid = sid;
    if (sidChangedL)
    {
        emit sidChanged(d->sid);
    }
}

void GoogleLoginData::setSavePassword(bool val)
{
    QMutexLocker locker(&d->isPasswordSavedMutex);
    bool isPasswordSavedStatusChangedL = d->isPasswordSaved != val;
    d->isPasswordSaved = val;
    if (isPasswordSavedStatusChangedL)
    {
        emit isPasswordSavedStatusChanged(d->isPasswordSaved);
    }
}

void GoogleLoginData::setAlwaysAskPassword(bool val)
{
    QMutexLocker locker(&d->alwaysAskPasswordMutex);
    d->alwaysAskPassword = val;
}

void GoogleLoginData::askPasswordFromUser()
{
    bool ok;
    QString text = QInputDialog::getText(0, QCoreApplication::applicationName(),
            tr("Please enter Google account password\nfor \"%1\":").arg(email() ), QLineEdit::Password,
            QString(), &ok);
    if (ok)
    {
        setPassword(text);
    }
    else setPassword("");
}
